#ifndef _BITMASK_HASH_H_
#define _BITMASK_HASH_H_

#include <math.h>

template <class T>
struct BitMaskHash
{
};

/**
* Bit Mask hash for int
*/
template <>
struct BitMaskHash<int>
{
	size_t operator()(const int& X, const int& S)
	{
	return (abs(X)) & ((1<<S)-1);
	}
};

/**
* Bit Mask hash for short
*/
template <>
struct BitMaskHash<short>
{
	size_t operator()(const short& X, size_t S)
	{
	return	(X & ((1<<S)-1));
	
	}
};

/**
* Bit Mask hash for unsigned short
*/
template <>
struct BitMaskHash<unsigned short>
{
	size_t operator()(const unsigned short& X, size_t S)
	{
		return (X & ((1<<S)-1));
	}
};

/**
* Bit Mask hash for unsigned int
*/
template <>
struct BitMaskHash<unsigned int>
{
	size_t operator()(const unsigned int& X, size_t S)
	{
	return (X & ((1<<S)-1));

	}
};

/**
* Bit Mask hash for long
*/
template <>
struct BitMaskHash<long>
{
	size_t operator()(const long& X, size_t S)
	{
	return (X & ((1<<S)-1));
	}
};

/**
* Bit Mask hash for unsigned long
*/
template <>
struct BitMaskHash<unsigned long>
{
	size_t operator()(const unsigned long& X, size_t S)
	{
	return (X & ((1<<S)-1));
	}
};

/**
* Bit Mask hash for char string
*/
template <>
struct BitMaskHash<char*>
{
	size_t operator()(const char* X, size_t S)
	{
		char* Y = const_cast<char*>(X);
		unsigned long hash = 5381;
		int c;
		while ((c = *Y++))
			hash = ((hash << 5) + hash) + c;
		return (hash &= ((1<<S)-1));
	}
};

/**
* Bit Mask hash for double
*/
template <>
struct BitMaskHash<double>
{
	size_t operator()(const double& X, size_t S)
	{
		double Y = X;
		unsigned long hash = 5381;
		Y = X - floor(X);
		return  ((abs((long)(Y * hash))) & ((1<<S)-1));
	}
};

/**
* Bit Mask hash for float
*/
template <>
struct BitMaskHash<float>
{
	size_t operator()(const float& X, size_t S)
	{
		float Y = X;
		unsigned long hash = 5381;
		Y = X - floor(X);
		return  ((abs((long)(Y * hash))) & ((1<<S)-1));
	}
};

/**
* Bit Mask hash for long double
*/
template <>
struct BitMaskHash<long double>
{
	size_t operator()(long double& X, size_t S)
	{
		long double Y = X;
		unsigned long hash = 5381;
		Y = X - floor(X);
		return  ((abs((long)(Y * hash))) & ((1<<S)-1));
	}
};


template <class Config_>
struct SimpleBitMaskHash
{
	typedef Config_ Config;
	typedef typename Config::KeyType key_type;

	size_t operator()(const key_type& k)
	{
		BitMaskHash<key_type> hasher;
		return hasher(k, Config::max_size);
	}
};


#endif
